from ckeditor_uploader.fields import RichTextUploadingField
from django.db import models

from mlh.utils.models import BaseModel


# 总结:
#   1.user = models.OneToOneField(to=UserDetail) # 指定一对一的关系
#     user.userdetail(user对象拿关联的userdetail对象)
#     userdetail.userdetail
#
#   2.goods = models.ManyToManyField(to=Customer,through='Cart',through=['goods','customer']) # 指定多对多的关系
#     Goods:商品表
#     Customer:客户表
#     Cart:购物车表(当不指定多对多的第三张表的时候,ManyToManyField会自动创建第三张表)
#     customer.goods(customer对象拿关联的goods对象)
#     goods.customer_set(同理)
#   3.使用OneToOneField和ManyToManyField去指定的时候,在关联查询的时候非常方便
#   4.CommentFollow.objects.all().only('comment','tucao') 使用only()指定要查询的列,增肌数据库查询性能
#   5.关于序列化器嵌套查询的时候,如果我们不做任何优化,会生成非常多的重复的sql语句执行,解决办法:(合并多余的sql语句)
#     queryset = Tucao.objects.all().select_related('user')  # 多查一(从多的一方嵌套查询一的一方的信息,user是指定的外键,默认所有)
#     queryset = User.objects.all().prefetch_related('tucao_set')  # 一查多('tucao_set'指定的关联的多的表的集)
#     queryset = User.objects.all().prefetch_related('tucao_set__comment_set')  # 一查多,多次嵌套
#     queryset = Tucao.objects.all().select_related('user').prefetch_related('comment_set')  # 同时多查一,一查多
#
#     务必注意:
#     (1)select_related()和prefetch_related()调用的对象都是Table.objects.all()即使链式调用,调用的对象仍然是Table.objects.all()
#         如果涉及到更深层的嵌套使用'tucao_set__comment_set',一层一层拼接
#     (2)序列化器仍然要使用嵌套的形式
#  6.进阶:一查多进阶(直接在后端对查出来的一查多中的多进行分类)
#   创建Prefetch()对象,将Prefetch()传入prefetch_related()中,可以传入多个Prefetch(),每一个Prefetch()对应一个自主分类
#   queryset = User.objects.all().prefetch_related('tucao_set')
#   变换:
#   queryset = User.objects.all().prefetch_related(p1,p2)
#   p1 = Prefetch(lookup='tucao_set',queryset=Tucao.objects.all().only('comment','tucao').select_related('user').prefetch_related('comment_set'),
#          to_attr='tucao')
#   p2 = Prefetch(lookup='tucao_set',queryset=Tucao.objects.all().only('comment','tucao').select_related('user').prefetch_related('comment_set'),
#          to_attr='block')
#   (1)lookup:需要指定的差多的多的关联的表(比如user的tucao)
#   (2)queryset:tucao_set对应表的tucao进行queryset筛选,并且可以传入所有的优化方式如:only(),select_related(),prefetch_related()
#   (3)to_attr:分类过后指定的分类名
#   但是注意:每一个Prefetch都有一个query_set,我们需要对每个用来分类的字段指定一个嵌套的序列化器,如:
#   tucao = TucaoSerializer(many=True)
#   block = TucaoSerializer(many=True)
#
#  7.当冗余字段多的时候,可以将冗余字段拆出去作为一个一对一的表(字段少,查询快),当有多个拆出去的表字段非常一致的时候
#    我们可以将这些表合并,添加一列用于指向各自的表(表的类型),并且将各自的记录的id设置为数值类型作为逻辑外键指向各自的记录
#    解决问题:逻辑关联的表查询和排序
#    (1)在django中使用原生的sql查询语句---连表查(可以链表并且指定排序规则)
#       Tucao.objects.raw(原生的sql,[变量]) 原生的sql = "select **************** %s,*********"
#       务必注意:Tucao.objects只是根据Tucao表创建了一个接受原生的sql查询出来的记录的框架,只要查询的记录与Tucao.objects兼容即可,
#       也就是说Tucao.objects与原生的sql的查询结构没有必然联系,记者使用任何兼容的Table.objects
#    (2)在django中使用数据库的视图---直接在数据库视图的模型中指定排序规则
#       首先在数据库中创建视图,
#       然后创建视图的模型类
#       模型类需要注意的地方:1.字段为视图中指定的字段,2.指定class Meta:中===>managed = False (不迁移) , db_table = "" (指定数据库视图的表名)
#         3.视图模型的操作与普通的模型一致,只是不生成具体的模型迁移的表
#
#
#    (拆出去的表有个type字段,标示关联的表名),假设拆出去的表叫:Test
#    如:表Tucao,

class Tucao(BaseModel):
    """吐槽表"""
    # content = models.TextField(verbose_name='吐槽内容')
    content = RichTextUploadingField(default='',verbose_name='吐槽内容')
    user = models.ForeignKey('users.User', null=True, blank=True, related_name='tucaos',
                             verbose_name='作者')
    follow_count = models.IntegerField(default=0, verbose_name='点赞数')
    comment_count = models.IntegerField(default=0, verbose_name='评论数')
    share_count = models.IntegerField(default=0, verbose_name='分享数')
    username = models.CharField(max_length=32, null=True, blank=True, verbose_name='作者名')

    class Meta:
        db_table = 'tb_tucao'
        verbose_name = '吐槽'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.username or self.user.username
        return 'ID: ' + str(self.id) + '  作者: ' + str(user)


class Image(models.Model):
    """图片表"""
    image = models.CharField(max_length=128, verbose_name='图片')
    tucao = models.ForeignKey(Tucao, on_delete=models.CASCADE, related_name='images', verbose_name='吐槽')

    class Meta:
        db_table = 'tb_image'
        verbose_name = '图片'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.tucao.username or self.tucao.user.username
        return 'ID: ' + str(self.tucao.id) + '  作者: ' + str(user)


class Comment(BaseModel):
    """评论表"""
    content = RichTextUploadingField(default='',verbose_name='评论内容')
    user = models.ForeignKey('users.User', null=True, related_name='comments', verbose_name='作者')
    tucao = models.ForeignKey(Tucao, on_delete=models.CASCADE, related_name='comments', verbose_name='吐槽')
    count = models.IntegerField(default=0, verbose_name='点赞数')
    username = models.CharField(max_length=32, null=True, blank=True, verbose_name='作者名')
    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subs',
                               verbose_name='父评论')

    class Meta:
        db_table = 'tb_comment'
        verbose_name = '评论'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.username or self.user.username
        return 'ID: ' + str(self.id) + '  作者: ' + str(user)


class TucaoFollow(BaseModel):
    """吐槽点赞表"""

    tucao = models.ForeignKey(Tucao, on_delete=models.CASCADE, verbose_name='吐槽')
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')

    class Meta:
        db_table = 'tb_tucao_follow'
        verbose_name = '吐槽点赞'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.tucao.username or self.tucao.user.username
        return 'ID: ' + str(self.tucao.id) + '  作者: ' + str(user)


class Collections(BaseModel):
    """吐槽收藏表"""
    tucao = models.ForeignKey(Tucao, on_delete=models.CASCADE, verbose_name='吐槽')
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')

    class Meta:
        db_table = 'tb_collections_follow'
        verbose_name = '吐槽收藏'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.tucao.username or self.tucao.user.username
        return 'tucao: ' + str(self.tucao.id) + '  user: ' + str(user)


class CommentFollow(BaseModel):
    """评论点赞表"""
    tucao = models.ForeignKey(Tucao, on_delete=models.CASCADE, verbose_name='吐槽')
    comment = models.ForeignKey(Comment, on_delete=models.CASCADE, verbose_name='评论')
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')

    class Meta:
        db_table = 'tb_comment_follow'
        verbose_name = '评论点赞'
        verbose_name_plural = verbose_name

    def __str__(self):
        user = self.comment.username or self.comment.user.username
        return 'ID: ' + str(self.comment.id) + '  作者: ' + str(user)


